package com.project.controller;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.project.entity.OutOrder;
import com.project.entity.OutOrderInfo;
import com.project.entity.PreOutOrder;
import com.project.entity.Product;
import com.project.service.PreOutOrderService;
import com.project.util.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@RestController
@Api(tags = "出库单接口")
@RequestMapping("preOutOrder")
public class PreOutOrderController {
    @Autowired
    private PreOutOrderService preOutOrderService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private RLock rLock;

    @ApiOperation(value = "按客户ID、销售员ID查询出库单信息集合")
    @GetMapping("findByCustomId/{customId}/{userId}")
    public List<PreOutOrder> findByCustomId(@PathVariable("customId") Integer customId, @PathVariable("userId") Integer userId) throws InterruptedException {
        String key = customId + "_" + userId;
        if (redisTemplate.hasKey(key)) {
            //  存在缓存
            ValueOperations<String, Object> operations = redisTemplate.opsForValue();
            String json = (String) operations.get(key);
            return JSONObject.parseArray(json, PreOutOrder.class);
        } else {
            //  竞争锁
            boolean bl = rLock.tryLock(0, 10, TimeUnit.SECONDS);
            if (bl) {
                //  不存在缓存
                List<PreOutOrder> preOutOrderInfoList = preOutOrderService.findById(customId, userId);
                //  防止缓存雪崩
                //  每一个条件的hash值
                long codeNum = key.hashCode();
                //  随机获取到一个值 作为缓存时间
                int time = (int) codeNum % StringUtil.CACHE_TIME_MAX;
                //如果随机值小于最小缓存时间，那么该随机值就赋值为最小缓存时间值
                if (time < StringUtil.CACHE_TIME_MIN) {
                    time = StringUtil.CACHE_TIME_MIN;
                }
                if (preOutOrderInfoList.size() == 0) {
                    //  所查询的数据库对象值为null 将缓存时间变短 （防止故意攻击）
                    redisTemplate.opsForValue().set(key, JSON.toJSONString(preOutOrderInfoList), StringUtil.CACHE_TIME_MIN, TimeUnit.SECONDS);
                } else {
                    redisTemplate.opsForValue().set(key, JSON.toJSONString(preOutOrderInfoList), time, TimeUnit.SECONDS);
                    return preOutOrderInfoList;
                }
                rLock.unlock();//   释放锁
            } else {
                //  没有竞争到锁
                Thread.sleep(500);//    休眠500毫秒
                this.findByCustomId(customId, userId);//   重新竞争锁
            }
        }
        return new ArrayList<>();
    }

    @ApiOperation(value = "修改出库数量")
    @PutMapping("UpdateOutNum")
    public boolean UpdateOutNum(Integer preOutId, Integer productId, Integer newOutNum) {
        return preOutOrderService.UpdateOutNum(preOutId, productId, newOutNum);
    }

    @ApiOperation(value = "按商品ID添加商品")
    @PostMapping("addProductById")
    public String addProductById(Integer productId, Integer customId, Integer sellerId) {
        preOutOrderService.addProductById(productId, customId, sellerId);
        return "ok";
    }

    @ApiOperation(value = "按商品ID移除商品")
    @DeleteMapping("delProductById/{productId}/{customId}/{sellerId}")
    public String delProductById(@PathVariable("productId") Integer productId, @PathVariable("customId") Integer customId, @PathVariable("sellerId") Integer sellerId) {
        preOutOrderService.delProductById(productId, customId, sellerId);
        return "ok";
    }

    @ApiOperation(value = "出库")
    @PutMapping("outBound")
    public String outBound(OutOrder outOrder) {
        preOutOrderService.outBound(outOrder);
        return "ok";
    }
}
